package com.codeoss.framework.view.service.impl;

import java.util.List;
import java.util.Map;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import com.codeoss.framework.context.YunContext;
import com.codeoss.framework.converter.IConverter;
import com.codeoss.framework.converter.IConverterStore;
import com.codeoss.framework.data.metadata.Query;
import com.codeoss.framework.data.metadata.Restrictions;
import com.codeoss.framework.data.metadata.Table;
import com.codeoss.framework.data.store.ITableStore;
import com.codeoss.framework.expression.Expression;
import com.codeoss.framework.view.component.Component;
import com.codeoss.framework.view.component.Page;
import com.codeoss.framework.view.component.Tree;
import com.codeoss.framework.view.datasource.DataSourceConfig;
import com.codeoss.framework.view.datasource.IDataSource;
import com.codeoss.framework.view.datasource.store.IDataSourceStore;
import com.codeoss.framework.view.model.HierarchyData;
import com.codeoss.framework.view.service.IVariableService;
import com.codeoss.framework.view.util.DataSourceUtil;

@Service
public class TreeComponentService extends ComponentService {
	@Autowired
    private IVariableService variableService;
	@Autowired
	private IConverterStore converterStore;
	@Autowired
	private IDataSourceStore dataSourceStore;
	@Autowired
	private ITableStore tableStore;
	@Autowired
	private DataSourceUtil dataSourceUtil;
	@Override
	public void processValue(YunContext yunContext, Component component,Map<String,String> paraMap,Map<String,Object> dataMap) {
		// TODO Auto-generated method stub
		Tree tree=(Tree)component;
		if(paraMap.containsKey(tree.getId())) {
			String sValue=paraMap.get(tree.getId());
			IConverter converter=converterStore.getConverter("long");
			Object value=converter.convertStringToObject(sValue);
			variableService.setVariableValue(yunContext, tree.getVarName(), value);
		}
	}
	
	@Override
	public void processEvent(YunContext yunContext, Component component, String eventType) {
		// TODO Auto-generated method stub
		super.processEvent(yunContext, component, eventType);
		Tree tree=(Tree)component;
		if ("itemClickEvent".equals(eventType)) {
			Expression onItemClickExpression = tree.getOnItemClickExpression();
			if (onItemClickExpression != null) {
				executeEventExpression(yunContext, component, onItemClickExpression,null);
			}
		}else if ("moveNodeEvent".equals(eventType)) {
			Map<String, String> queryMap = yunContext.getViewRequest().getData();
			String sSourceId = queryMap.get(component.getId() + "_sourceId");
			String sTargetId = queryMap.get(component.getId() + "_targetId");
			String moveType = queryMap.get(component.getId() + "_moveType");
			Long sourceId = Long.parseLong(sSourceId);
			Long targetId = Long.parseLong(sTargetId);
			moveNode(yunContext, component, sourceId, targetId, moveType);
		}
	}
	
	protected void moveNode(YunContext yunContext, Component component,Long sourceId,Long targetId,String moveType) {
		Tree tree=(Tree)component;
		Page page = yunContext.getPage();
		DataSourceConfig dataSourceConfig=dataSourceUtil.getDataSourceConfigById(page, tree.getDataSource());
		String keyColumnName="id";
		Query sourceQuery=new Query();
		sourceQuery.add(Restrictions.eq(keyColumnName, sourceId));
		Table table=tableStore.get(dataSourceConfig.getTableName());
		IDataSource dataSource=dataSourceStore.getDataSource(table.getAccessType());
		Map<String,Object> sourceMap=(Map<String,Object>)dataSource.select(yunContext, table,sourceQuery).getData().get(0);
		
		Query targetQuery=new Query();
		targetQuery.add(Restrictions.eq(keyColumnName, targetId));
		Map<String,Object> targetMap=(Map<String,Object>)dataSource.select(yunContext, table,targetQuery).getData().get(0);
		
		Map<String,Object> parentMap=null;
		if("before".equals(moveType)) {
			sourceMap.put("seq_no",(Integer)targetMap.get("seq_no")-1);
			Query parentQuery=new Query();
			parentQuery.add(Restrictions.eq(keyColumnName, targetMap.get("parent_id")));
			parentMap=(Map<String,Object>)dataSource.select(yunContext,table, parentQuery).getData().get(0);
		}else if("after".equals(moveType)) {
			sourceMap.put("seq_no",(Integer)targetMap.get("seq_no")+1);
			Query parentQuery=new Query();
			parentQuery.add(Restrictions.eq(keyColumnName, targetMap.get("parent_id")));
			parentMap=(Map<String,Object>)dataSource.select(yunContext, table,parentQuery).getData().get(0);
		}else if("inner".equals(moveType)) {
			parentMap=targetMap;
		}
		sourceMap.put("parent_id",parentMap.get("id"));
		dataSource.update(yunContext, table,sourceMap);
		Query descendQuery=new Query();
		String path=(String)sourceMap.get("path");
		descendQuery.add(Restrictions.likeRight("path", path));
		List<Map<String,Object>> dataList=dataSource.select(yunContext, table,descendQuery).getData();
		HierarchyData hierarchyData=dataSourceUtil.convertTableDataToHierarchyData(yunContext, dataList);
		Long parentId=(Long)parentMap.get("id");
		resetPath(yunContext,dataSource,table,hierarchyData,parentId);
	}
	
	protected void resetPath(YunContext yunContext,IDataSource dataSource,Table table,HierarchyData hierarchyData,Long parentId) {
		Query parentQuery=new Query();
		parentQuery.add(Restrictions.eq("id", parentId));
		Map<String,Object> parentMap=(Map<String,Object>)dataSource.select(yunContext, table,parentQuery).getData().get(0);
		String parentPath=(String)parentMap.get("path");
		
		Query query=new Query();
		Long id=Long.parseLong(hierarchyData.getId());
		query.add(Restrictions.eq("id", id));
		Map<String,Object> map=(Map<String,Object>)dataSource.select(yunContext, table,query).getData().get(0);
		map.put("path", parentPath+hierarchyData.getId()+",");
		dataSource.update(yunContext,table, map);
		
		List<HierarchyData> childList=hierarchyData.getChildren();
		if(childList!=null) {
			for(int i=0;i<childList.size();i++) {
				HierarchyData childData=childList.get(i);
				resetPath(yunContext,dataSource,table,childData,id);
			}
		}
	}
}
